/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "imageknife_dispatcher.h"
#include "imageknife_internal.h"
#include "imageknife_node_image.h"
#include "task_worker.h"
#include "utils/imageknife_trace.h"
namespace ImageKnifePro {

ImageKnifeNodeImage::ImageKnifeNodeImage(std::shared_ptr<ImageKnifeOption> option)
    : ImageKnifeNodeInternal(option, GetNodeAPI()->createNode(ARKUI_NODE_IMAGE)), useOnComplete_(true)
{
    IMAGE_KNIFE_CHECK(option == nullptr, "NULL ImageKnifeOption");
    if (option->objectFit != ARKUI_OBJECT_FIT_AUTO) {
        SetPercentWidth(1);
        SetPercentHeight(1);

#ifndef IMAGEKNIFE_EXECUTE_REQUEST_ON_NAPI_CREATE_NODE
    } else {
        // 自适应宽高,不需要降采样, 不使用父组件百分比, 不会触发测算需要手动Execute
        auto request = GetImageKnifeRequest();
        auto func = [request](void *) {
            ImageKnifeInternal::GetInstance().Execute(request);
        };
        TaskWorker::GetInstance()->ToMainThread(func, nullptr);
#endif
    }

    // 由于C侧ARKUI_NODE_IMAGE目前接收超超大图片时会爆栈崩溃，因此暂时屏蔽None策略改为Default对超大图片进行降采样
    // 图片分辨率低于7680 * 4320则不受影响，行为与None一致
    if (option->downSampling == DownSamplingStrategy::NONE) {
        option->downSampling = DownSamplingStrategy::DEFAULT;
    }

    onImageComplete_ = option->onComplete;
    if (onImageComplete_ != nullptr) {
        GetNodeAPI()->registerNodeEvent(handle, NODE_IMAGE_ON_COMPLETE, 0, nullptr);
    }
    Draggable(false);
}

bool ImageKnifeNodeImage::DrawingFrame(std::shared_ptr<ImageDataCacheInternal> data, int frameCount)
{
    IMAGE_KNIFE_CHECK_RETURN(data == nullptr, false);
    IMAGE_KNIFE_CHECK_RETURN(data->GetDrawableDescriptorList() == nullptr, false);
    IMAGE_KNIFE_CHECK_RETURN(frameCount < 0 || frameCount > data->GetFrameCount() - 1, false);

    ArkUI_AttributeItem item = {.object = data->GetDrawableDescriptorList()[frameCount]};
    IMAGE_KNIFE_CHECK_RETURN(item.object == nullptr, false);
    GetNodeAPI()->setAttribute(handle, NODE_IMAGE_SRC, &item);
    return true;
}

bool ImageKnifeNodeImage::Display(std::shared_ptr<ImageDataCacheInternal> data, bool isMainSrc)
{
    IMAGE_KNIFE_CHECK_RETURN(data == nullptr, false);
    if (isMainSrc) {
        mainData_ = data;
        triggerOnCompleteCallback_ = true;
    }

    ImageKnifeTrace trace("SetPixelmap");
    trace.StartSyncTrace();

    imageVersionId_++;
    if (data->GetFrameCount() > 1) {
        playAnimation_ = true;
        return DisplayAnimation(data);
    } else if (data->GetDrawableDescriptor() != nullptr) {
        playAnimation_ = false;
        return DrawingFrame(data);
    }

    return false;
}

void ImageKnifeNodeImage::DecodeFrame(bool immediately)
{
    IMAGE_KNIFE_CHECK(animationData_ == nullptr);
    auto fileBuffer = animationData_->GetFileBuffer();
    IMAGE_KNIFE_CHECK(fileBuffer == nullptr);
    auto option = animationData_->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    auto request = std::make_shared<ImageKnifeRequestInternal>(option, imageVersionId_);
    request->SetComponentId(GetComponentId());

    decodeTask_ = std::make_shared<ImageKnifeTaskInternal>(fileBuffer, animationData_->GetImageCacheSize(),
        currentFrame_, animationData_->requestType, request);
    decodeTask_->SetImageFormat(animationData_->type);
    decodeTask_->SetDesiredSize(animationData_->GetPixelmapSize());

    auto decodeImageSource = decodeImageSource_;
    auto execute = [immediately, decodeImageSource](std::shared_ptr<ImageKnifeTaskInternal> task) {
        // 组件内复用解码ImageSource，不复用解码耗时会增加
        std::shared_ptr<DecodeImageSource> imageSource = nullptr;
        if (immediately) {
            imageSource = std::make_shared<DecodeImageSource>(task->product.imageBuffer.get(),
                                                              task->product.imageLength);
        } else {
            imageSource = decodeImageSource;
        }
        task->SetDecodeImageSource(imageSource);
        ImageKnifeDispatcher::GetInstance().ProcessFrameModeDecoding(task);
    };

    auto weak = this->weak_from_this();
    int versionId = imageVersionId_;
    auto complete = [immediately, versionId, weak](std::shared_ptr<ImageKnifeTaskInternal> task) {
        auto self = weak.lock();
        if (self == nullptr) {
            return;
        }
        if (versionId == self->imageVersionId_ && immediately) {
            self->decodeImageSource_ = task->GetDecodeImageSource();
        }

        /**
         * 解码和延时任务同时完成才开始下一帧
         * 1. immediately成立：该动图首次播放或恢复播放，需要解码后立即显示，不进行延时等待
         * 2. 延时任务已执行，解码超时，立即显示
         */
        if (immediately || task->IsDecodeFrameFinished()) {
            self->DisplayNextFrame(versionId);
        } else {
            // 当前帧播放时长尚未结束，等待延时任务触发去显示
            task->MarkDecodeFrameFinished();
        }
    };
    TaskWorker::GetInstance()->PushTask(execute, complete, decodeTask_);
}

void ImageKnifeNodeImage::CancelPreviousAnimation()
{
    // 取消延时任务
    if (animationTaskHandle_ != nullptr) {
        animationTaskHandle_->CancelTask();
    }

    if (decodeTask_ != nullptr) {
        auto request = decodeTask_->GetImageKnifeRequestInternal();
        if (request != nullptr) {
            request->Destroy();
        }
        auto interceptor = decodeTask_->GetCurrentInterceptor();
        if (interceptor != nullptr) {
            interceptor->Cancel(decodeTask_);
        }
        decodeTask_ = nullptr;
    }
}

bool ImageKnifeNodeImage::DisplayAnimation(std::shared_ptr<ImageDataCacheInternal> data)
{
    IMAGE_KNIFE_CHECK_RETURN(data->GetFrameCount() <= 1, false);
    if (data->GetFileBuffer() != nullptr) {
        IMAGE_KNIFE_CHECK_RETURN(data->GetImageKnifeOption() == nullptr, false);
    } else {
        IMAGE_KNIFE_CHECK_RETURN(data->GetDrawableDescriptorList() == nullptr, false);
    }

    // 取消之前的播放任务
    CancelPreviousAnimation();

    initialFrame_ = reverse_ ? data->GetFrameCount() - 1 : 0;
    lastFrame_ = reverse_ ? 0 : data->GetFrameCount() - 1;
    currentFrame_ = animationState_ == ARKUI_ANIMATION_STATUS_STOPPED ? lastFrame_ : initialFrame_;
    currentIteration_ = 0;
    animationData_ = data;

    if (animationState_ == ARKUI_ANIMATION_STATUS_RUNNING &&
        animatorOption_ != nullptr && animatorOption_->onStart != nullptr) {
        animatorOption_->onStart();
    }

    if (data->GetFileBuffer() != nullptr) {
        // 逐帧解码模式，首次先解码
        DecodeFrame(true);
    } else {
        // 批量解码模式直接播放
        DisplayNextFrame(imageVersionId_);
    }

    return true;
}

void ImageKnifeNodeImage::AnimationIterate()
{
    if (reverse_) {
        currentFrame_--;
    } else {
        currentFrame_ ++;
    }

    if (currentFrame_ < 0 || currentFrame_ > (animationData_->GetFrameCount() -1)) {
        currentFrame_ = initialFrame_;
        currentIteration_++;
        if (iterations_ != -1 && currentIteration_ >= iterations_) {
            // 播放结束
            animationState_ = ARKUI_ANIMATION_STATUS_STOPPED;
        }
    }
}

void ImageKnifeNodeImage::DisplayCurrentFrame()
{
    if (animationData_->GetFileBuffer() != nullptr) {
        // 逐帧解码模式
        if (decodeTask_ != nullptr && decodeTask_->IsSuccess()) {
            auto dataCache = std::dynamic_pointer_cast<ImageDataCacheInternal>(decodeTask_->product.imageDataCache);
            if (dataCache == nullptr) {
                decodeTask_->EchoError("Empty DataCache After Decode Frame:" + std::to_string(currentFrame_));
                return;
            }
            DrawingFrame(dataCache, 0);
        }
    } else {
        // 批量解码模式
        DrawingFrame(animationData_, currentFrame_);
    }
}

void ImageKnifeNodeImage::DisplayNextFrame(int versionId)
{
    // 过期动图loop不再继续播放
    if (versionId != imageVersionId_) {
        return;
    }

    // 播放迭代非首次，且完整播放一次，触发onRepeat回调
    if (currentIteration_ > 0 && currentFrame_ == initialFrame_ &&
        animatorOption_ != nullptr && animatorOption_->onRepeat != nullptr) {
        animatorOption_->onRepeat();
    }

    // 播放当前帧
    DisplayCurrentFrame();

    // 确认下一帧
    AnimationIterate();

    if (animationState_ != ARKUI_ANIMATION_STATUS_RUNNING) {
        if (animationState_ == ARKUI_ANIMATION_STATUS_STOPPED &&
            animatorOption_ != nullptr && animatorOption_->onFinish != nullptr) {
            animatorOption_->onFinish();
        }
        return;
    }

    // 延时播放下一帧
    PrepareNextFrame(versionId);
}

void ImageKnifeNodeImage::PrepareNextFrame(int versionId)
{
    int *delayList = nullptr;
    auto weak = this->weak_from_this();
    std::function<void(void *)> func = nullptr;
    if (animationData_->GetFileBuffer() != nullptr) {
        // 逐帧解码模式
        delayList = animationData_->GetAnimationDelayTimeList();
        DecodeFrame(false);
        // 这里需持有task, 否则主线程返回时，task可能因图片变更而错误标记
        auto task = decodeTask_;
        func = [weak, task, versionId](void *) {
            auto self = weak.lock();
            if (self == nullptr) {
                return;
            }
            if (task->IsDecodeFrameFinished()) {
                self->DisplayNextFrame(versionId);
            } else {
                task->MarkDecodeFrameFinished();
            }
        };
    } else {
        // 批量解码模式
        delayList = animationData_->GetImageData()->GetDelayTimeList();
        func = [weak, versionId](void *) {
            auto self = weak.lock();
            if (self != nullptr) {
                self->DisplayNextFrame(versionId);
            }
        };
    }

    int delayTime = delayList == nullptr ? 100 : (delayList[currentFrame_] < 40 ? 40 : delayList[currentFrame_]);
    animationTaskHandle_ = TaskWorker::GetInstance()->ToMainThreadWithDelay(func, nullptr, delayTime);
}

void ImageKnifeNodeImage::TerminateAnimation()
{
    imageVersionId_++;
    CancelPreviousAnimation();
    animationData_ = nullptr;
}

void ImageKnifeNodeImage::UpdateAnimatorOption(std::shared_ptr<AnimatorOption> option)
{
    animatorOption_ = option;
    if (animatorOption_ == nullptr) {
        return;
    }
    iterations_ = animatorOption_->iterations;
    reverse_ = animatorOption_->reverse;

    if (!playAnimation_) {
        animationState_ = animatorOption_->state;
        return;
    }

    IMAGE_KNIFE_CHECK(animationData_ == nullptr);
    IMAGE_KNIFE_CHECK(animationData_->GetFrameCount() <= 1);

    if (animatorOption_->state == ARKUI_ANIMATION_STATUS_PAUSED) {
        AnimationSwitchToPause();
    } else if (animatorOption_->state == ARKUI_ANIMATION_STATUS_RUNNING) {
        AnimationSwitchToRunning();
    } else if (animatorOption_->state == ARKUI_ANIMATION_STATUS_INITIAL) {
        AnimationSwitchToInitial();
    } else if (animatorOption_->state == ARKUI_ANIMATION_STATUS_STOPPED) {
        AnimationSwitchToStop();
    }
}

void ImageKnifeNodeImage::AnimationSwitchToRunning()
{
    if (animationState_ == ARKUI_ANIMATION_STATUS_PAUSED) {
        // 从Pause恢复播放
        animationState_ = animatorOption_->state;
        if (animatorOption_->onStart != nullptr) {
            animatorOption_->onStart();
        }
        DisplayNextFrame(imageVersionId_);
    } else if (animationState_ != ARKUI_ANIMATION_STATUS_RUNNING) {
        animationState_ = animatorOption_->state;
        // 从首帧开始播放
        DisplayAnimation(animationData_);
    } else {
        // 为正在播放的动图重新计算首尾帧
        initialFrame_ = reverse_ ? animationData_->GetFrameCount() - 1 : 0;
        lastFrame_ = reverse_ ? 0 : animationData_->GetFrameCount() - 1;
    }
}

void ImageKnifeNodeImage::AnimationSwitchToStop()
{
    if (animationState_ != ARKUI_ANIMATION_STATUS_STOPPED ||
        lastFrame_ != (reverse_ ? 0 : animationData_->GetFrameCount() - 1)) {
        // 仅播放尾帧
        animationState_ = animatorOption_->state;
        DisplayAnimation(animationData_);
    }
}

void ImageKnifeNodeImage::AnimationSwitchToInitial()
{
    // 当前为Running转换到初始状态，触发onCancel
    if (animationState_ == ARKUI_ANIMATION_STATUS_RUNNING && animatorOption_->onCancel != nullptr) {
        animatorOption_->onCancel();
    }
    if (animationState_ != ARKUI_ANIMATION_STATUS_INITIAL ||
        initialFrame_ != (reverse_ ? animationData_->GetFrameCount() - 1 : 0)) {
        // 仅播放首帧
        animationState_ = animatorOption_->state;
        DisplayAnimation(animationData_);
    }
}

void ImageKnifeNodeImage::AnimationSwitchToPause()
{
    if (animationState_ == ARKUI_ANIMATION_STATUS_RUNNING) {
        // 从Running到Pause，暂停播放触发回调
        animationState_ = animatorOption_->state;
        if (animationTaskHandle_ != nullptr) {
            animationTaskHandle_->CancelTask();
        }

        if (animatorOption_->onPause != nullptr) {
            animatorOption_->onPause();
        }
    }
}

void ImageKnifeNodeImage::SetResizeableOption(std::shared_ptr<ResizableOption> resizeable)
{
    IMAGE_KNIFE_CHECK(resizeable == nullptr);
    const size_t four = 4;
    ArkUI_NumberValue numValue[four] = {
        {.f32 = resizeable->left}, {.f32 = resizeable->top},
        {.f32 = resizeable->right}, {.f32 = resizeable->bottom}
    };
    ArkUI_AttributeItem item = {.value = numValue, .size = four};
    GetNodeAPI()->setAttribute(handle, NODE_IMAGE_RESIZABLE, &item);
}

void ImageKnifeNodeImage::RemoveResizeableOption()
{
    GetNodeAPI()->resetAttribute(handle, NODE_IMAGE_RESIZABLE);
}
}